package com.dc.util;

import net.sf.cglib.beans.BeanCopier;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;


public class ListBeanUtils implements Serializable {

    private static final ConcurrentHashMap<String, BeanCopier> mapCaches = new ConcurrentHashMap<>();

    /**
     * @param source    原数据，list集合
     * @param sourceKey 原数据的实体类属性，为了防止空数据获取该属性报错
     * @param target    接收复制的数据实体类属性，会自动转换成list集合
     * @param <O>
     * @param <T>
     * @return
     */
    public static <O, T> List<T> listCopyMapper(List<O> source, Class<?> sourceKey, Class<?> target) {
        String baseKey = generateKey(sourceKey, target);
        BeanCopier copier;
        if (!mapCaches.containsKey(baseKey)) {
            copier = BeanCopier.create(sourceKey, target, false);
            mapCaches.put(baseKey, copier);
        } else {
            copier = mapCaches.get(baseKey);
        }
        List<T> targets = new ArrayList<>();
        try {
            source.stream().forEach(
                    bean -> {
                        T instance = null;
                        try {
                            instance = (T) target.getDeclaredConstructor().newInstance();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        }
                        copier.copy(bean, instance, null);
                        targets.add(instance);
                    }
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return targets;
    }


    private static String generateKey(Class<?> class1, Class<?> class2) {
        return class1.toString() + class2.toString();
    }


}